package backboneCode;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.uml2.common.util.CacheAdapter;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;

public class ModelCode {

	private URI typesUri = null;
	private RuleEngine ruleEngine = new RuleEngine();
	private RuleValidator ruleValidator = new RuleValidator();
	
	public Model getModel(String pathToModel) {
		
		typesUri = URI.createFileURI(pathToModel);
		ResourceSet set = new ResourceSetImpl();
		set.getPackageRegistry().put(UMLPackage.eNS_URI,
				UMLPackage.eINSTANCE);
		set.getResourceFactoryRegistry().getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, 
				UMLResource.Factory.INSTANCE);
		UMLPackage.eINSTANCE.eClass();
		Resource r = null;
		try {
			r = set.getResource(typesUri, true);
		} catch (Exception ex)
		{
			return null;
		}
        Model m = (Model) EcoreUtil.getObjectByType(r.getContents(), UMLPackage.Literals.MODEL);
		
		return m;
	}
	
	public void IterateArchModel(Model m) 
	{		
		for (org.eclipse.uml2.uml.Element element : m.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class) {
				ruleEngine.AddRuleSet(((org.eclipse.uml2.uml.Class) element).getName(), (org.eclipse.uml2.uml.Class) element);
			}
			IterateArchModel_(element);
		}
	}
	
	private org.eclipse.uml2.uml.Element IterateArchModel_(org.eclipse.uml2.uml.Element e)
	{
		for (org.eclipse.uml2.uml.Element element : e.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class) {
				ruleEngine.AddRuleSet(((org.eclipse.uml2.uml.Class) element).getName(), (org.eclipse.uml2.uml.Class) element);
			}
			IterateArchModel_(element);
			return element; //TODO: Are the return value needed??
		}
		return null; //TODO: Are the return value needed??
	}
	
	public void IterateSystemModel(Model m) 
	{
		ruleValidator.ValidateElement(m);
		
		for (org.eclipse.uml2.uml.Element element : m.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class 
					|| element instanceof org.eclipse.uml2.uml.Package) {
				ruleValidator.ValidateElement(element);			
				IterateSystemModel_(element);
			}
		}		
	}
		
	private void IterateSystemModel_(org.eclipse.uml2.uml.Element e) {
		
		for (org.eclipse.uml2.uml.Element element : e.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class 
					|| element instanceof org.eclipse.uml2.uml.Package) {
				ruleValidator.ValidateElement(element);	
				IterateSystemModel_(element);
			}
		}
	}

	public void ApplyRules(Model m) {
		ruleEngine.AppyRule((org.eclipse.uml2.uml.NamedElement)m);
		
		for (org.eclipse.uml2.uml.Element element : m.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class 
					|| element instanceof org.eclipse.uml2.uml.Package) {
				ruleEngine.AppyRule((org.eclipse.uml2.uml.NamedElement)element);			
				AppyRules_(element);
			}
		}
		
	}

	private void AppyRules_(org.eclipse.uml2.uml.Element e) {

		for (org.eclipse.uml2.uml.Element element : e.getOwnedElements()) {
			if (element instanceof org.eclipse.uml2.uml.Class 
					|| element instanceof org.eclipse.uml2.uml.Package) {
				ruleEngine.AppyRule((org.eclipse.uml2.uml.NamedElement)element);	
				AppyRules_(element);
			}
		}
	}
}